package org.linlinjava.litemall.wx.controller;

import cn.hutool.core.util.StrUtil;
import com.paypal.api.payments.Links;
import com.paypal.api.payments.Payment;
import io.swagger.annotations.Api;
import io.swagger.annotations.ApiImplicitParam;
import io.swagger.annotations.ApiImplicitParams;
import io.swagger.annotations.ApiOperation;
import lombok.RequiredArgsConstructor;
import lombok.SneakyThrows;
import org.apache.commons.lang3.StringUtils;
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import org.linlinjava.litemall.core.notify.AwsNotifyService;
import org.linlinjava.litemall.core.notify.NotifyService;
import org.linlinjava.litemall.core.util.ResponseUtil;
import org.linlinjava.litemall.core.validator.Order;
import org.linlinjava.litemall.core.validator.Sort;
import org.linlinjava.litemall.db.service.LitemallUserService;
import org.linlinjava.litemall.wx.annotation.LogAnno;
import org.linlinjava.litemall.wx.annotation.LoginUser;
import org.linlinjava.litemall.wx.constant.LitemallWXConstants;
import org.linlinjava.litemall.wx.dto.*;
import org.linlinjava.litemall.wx.service.WxGiftCardService;
import org.linlinjava.litemall.wx.util.URLUtils;
import org.linlinjava.litemall.wx.util.WxResponseEnum;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.validation.annotation.Validated;
import org.springframework.web.bind.annotation.*;
import springfox.documentation.annotations.ApiIgnore;

import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import javax.validation.Valid;
import javax.validation.constraints.NotNull;
import java.math.BigDecimal;

/**
 * 礼品卡控制器
 *
 * @author yliyun
 * @description：礼物卡
 * @date 2022/09/14
 */
@Api(tags = "WX礼物卡API")
@RestController
@RequestMapping("/wx/card")
@Validated
@RequiredArgsConstructor
public class GiftCardController {

    /**
     * url跑龙套
     */
    private final URLUtils urlUtils;

    private final WxGiftCardService giftCardService;

    private static Log log = LogFactory.getLog(GiftCardController.class);

    /**
     * 所有
     * 查询所有可购买的礼物卡，
     *
     * @param userId 用户id
     * @return {@link Object}
     */
    @GetMapping("all")
    @LogAnno
    public Object all(@LoginUser Integer userId){
        if(userId == null){
            return ResponseUtil.unlogin();
        }
        return giftCardService.all(userId);
    }

    /**
     * 细节
     * 礼物卡详情
     *
     * @param cardUserId 卡用户id
     * @return {@link Object}
     */
    @GetMapping("detail")
    @LogAnno
    public Object detail(@RequestParam("cardUserId") Integer cardUserId){
       return giftCardService.giftCardUserDetail(cardUserId);
    }

    /**
     * 改变默认卡片
     * 更改默认礼物卡
     *
     * @param userId     用户id
     * @param cardUserId 卡用户id
     * @return {@link Object}
     */
    @PutMapping("changeDefaultCard")
    @LogAnno
    public Object changeDefaultCard(@LoginUser Integer userId,@NotNull Integer cardUserId){
         return giftCardService.changeDefaultCard(userId,cardUserId);
    }


    @ApiOperation("购买礼物卡")
    @ApiImplicitParams({
            @ApiImplicitParam(name = "userId",value = "用户id"),
            @ApiImplicitParam(name = "cardId",value = "卡id"),
            @ApiImplicitParam(name = "amount",value = "金额"),
            @ApiImplicitParam(name = "shopId",value = "商店id"),
    })
    @PostMapping("buy")
    @LogAnno
    public Object buy(@ApiIgnore @LoginUser Integer userId, @NotNull Integer cardId, @NotNull BigDecimal amount, Integer shopId){
        if(userId == null){
            return ResponseUtil.unlogin();
        }
        return giftCardService.buyCard(userId, cardId,amount,shopId);
    }


    @ApiOperation("赠送礼物卡")
    @ApiImplicitParams({
            @ApiImplicitParam(name = "userId",value = "用户id"),
            @ApiImplicitParam(name = "cardId",value = "卡id"),
            @ApiImplicitParam(name = "amount",value = "金额"),
            @ApiImplicitParam(name = "givee",value = "被赠送人"),
            @ApiImplicitParam(name = "shopId",value = "商店id"),
    })
    @PostMapping("/give")
    @LogAnno
    public Object give(@ApiIgnore @LoginUser Integer userId,@NotNull Integer cardId,@NotNull BigDecimal amount
                       ,@NotNull String  givee,Integer shopId){
        return giftCardService.buyGiveCard(userId,cardId,amount,givee,shopId);
    }

    /**
     * 付款准备
     *
     * @param userId  用户id
     * @param orderId 订单id
     * @param resp    分别地
     * @param givee   givee
     * @param shopId  商店id
     * @return {@link Object}
     * @throws Exception 异常
     */
    @GetMapping("payAfterSuccess")
    @LogAnno
    @SneakyThrows
    public Object payAfterSuccess(@LoginUser Integer userId, @NotNull Integer orderId, HttpServletResponse resp,String givee,Integer shopId, String message){
        if(userId == null){
            return ResponseUtil.unlogin();
        }
        message= StrUtil.isNotEmpty(message)?message: LitemallWXConstants.WX_GIFTCARD_DEFAULT_MESSAGE;
//        if(givee != null){
//            if(givee.startsWith(MOBILE_CODE_ONE) && RegexUtil.isMobileValid(givee)){
//                givee = givee.substring(1,givee.length());
//            }
//        }

        Object obj =  giftCardService.getPayment(orderId, userId,givee,shopId,message);
        if(!(obj instanceof Payment)){
            return obj;
        }
        Payment payment = (Payment)obj;
        for(Links links : payment.getLinks()){
            if(links.getRel().equals("approval_url")){
                resp.sendRedirect(links.getHref().toString());
                return "redirect:" + links.getHref();
            }
        }
        return "<script type=\"text/javascript\">location.href=\"/\"</script>" ;
    }

    /**
     * 成功
     * 付款完成
     *
     * @param userId    用户id
     * @param paymentId 支付id
     * @param payerId   付款人身份
     * @param resp      分别地
     * @param request   请求
     * @return {@link Object}
     * @throws Exception 异常
     */
    @GetMapping("pay/success")
    @LogAnno
    public Object success(@LoginUser Integer userId, @NotNull @RequestParam("paymentId") String paymentId,@RequestParam("userName") String userName, @NotNull @RequestParam("PayerID") String payerId,HttpServletResponse resp, HttpServletRequest request) throws Exception{
        log.debug("paypal success");
        log.debug("更新订单信息之前");
        Object obj =  giftCardService.executePayment(paymentId, payerId);
        log.debug("更新订单信息成功");
        if(!(obj instanceof Payment)){
            return obj;
        }
        Payment payment = (Payment)obj;
        if(payment.getState().equals("approved")){

            //付款完成后生成礼物卡或者更新余额

            log.debug("开始创建礼物卡用户");
            giftCardService.createOrUpdateCard(userId,paymentId,userName);
            log.debug("创建礼物卡用户成功");
            log.info(urlUtils.getBaseURl());
            return ResponseUtil.ok("success");
        }
        return "<script type=\"text/javascript\">location.href=\"/\"</script>" ;
    }

    /**
     * 取消支付
     *
     * @return {@link Object}
     */
    @PostMapping("pay/cancel")
    @LogAnno
    public Object cancelPay(){
        return ResponseUtil.ok("cancel") ;
    }

    /**
     * 拒绝
     * 退款
     *
     * @param userId  用户id
     * @param orderId 订单id
     * @return {@link Object}
     */
    @PutMapping("refuse")
    @LogAnno
    public Object refuse(@LoginUser Integer userId, @NotNull Integer orderId){
        if(userId == null){
            return ResponseUtil.unlogin();
        }
        return giftCardService.refund(orderId,userId);
    }

    /**
     * 分享
     *
     * @param userId 用户id
     * @param dto    dto
     * @return {@link Object}
     */
    @PostMapping("share")
    @LogAnno
    public Object share(@LoginUser Integer userId, @Valid @RequestBody CardShareDTO dto){
        if(userId == null){
            return ResponseUtil.unlogin();
        }
        return giftCardService.share(dto, userId);
    }

    /**
     * 更新共享
     * 修改分享
     *
     * @param userId 用户id
     * @param dto    dto
     * @return {@link Object}
     */
    @PutMapping("share/update")
    @LogAnno
    public Object updateShare(@LoginUser Integer userId, @RequestBody CardShareDTO dto){
        if(userId == null){
            return ResponseUtil.unlogin();
        }
        if(dto.getId() == null){
            return ResponseUtil.fail(WxResponseEnum.IS_NULL_CARD_SHARE);
        }
        return giftCardService.updateShare(dto, userId);
    }

    /**
     * 取消
     * 取消分享
     *
     * @param userId      用户id
     * @param shareCardId 分享卡id
     * @return {@link Object}
     */
    @PutMapping("share/cancel")
    @LogAnno
    public Object cancel(@LoginUser Integer userId,  @NotNull Integer shareCardId){
        if(userId == null){
            return ResponseUtil.unlogin();
        }
        return giftCardService.shareCancel(shareCardId, userId);
    }

    /**
     * 找到
     * 根据link查找分享的礼物卡
     *
     * @param userId 用户id
     * @param link   链接
     * @return {@link Object}
     */
    @GetMapping("find")
    @LogAnno
    public Object find(@LoginUser Integer userId, @NotNull String link){
        if(userId == null){
            return ResponseUtil.unlogin();
        }
        return giftCardService.find(link);
    }

    /**
     * 选择
     * 领取礼物卡
     *
     * @param userId 用户id
     * @param link   链接
     * @param code   代码
     * @return {@link Object}
     */
    @PostMapping("pick")
    @LogAnno
    public Object pick(@LoginUser Integer userId,  @NotNull String link, @NotNull String code){
        if(userId == null){
            return ResponseUtil.unlogin();
        }
        return giftCardService.pick(link, code, userId);
    }

    /**
     * 我卡片
     * 我的礼物卡列表
     *
     * @param userId 用户id
     * @return {@link Object}
     */
    @ApiOperation(value = "我的礼物卡列表")
    @GetMapping("my")
    @LogAnno
    public Object myCards(@ApiIgnore @LoginUser Integer userId){
        if(userId == null){
            return ResponseUtil.unlogin();
        }
        return giftCardService.myCards(userId);
    }

    /**
     * 我虚拟卡
     * 我的虚拟卡
     *
     * @param userId 用户id
     * @return {@link Object}
     */
    @GetMapping("myVirtualCard")
    @LogAnno
    public Object myVirtualCard(@LoginUser Integer userId){
        return giftCardService.myVirtualCard(userId);
    }

    /**
     * 我股票
     * 我的分享列表
     *
     * @param userId 用户id
     * @return {@link Object}
     */
    @GetMapping("shares")
    @LogAnno
    public Object myShares(@LoginUser Integer userId){
        if(userId == null){
            return ResponseUtil.unlogin();
        }
        return giftCardService.myShares(userId);
    }

    /**
     * paypal充值
     *
     * paypal充值时吊起创建订单
     *
     * @param userId     用户id
     * @param cardNumber 卡号
     * @param amount     量
     * @param shopId     商店id
     * @return {@link Object}
     */
    @ApiOperation(value = "paypal充值")
    @GetMapping("recharge")
    @LogAnno
    public Object recharge(@LoginUser Integer userId, @RequestParam String cardNumber,@RequestParam BigDecimal amount,Integer shopId){
        if(userId == null){
            return ResponseUtil.unlogin();
        }
        if(StringUtils.isEmpty(cardNumber)){
            return ResponseUtil.badArgument();
        }
        if(amount == null){
            return ResponseUtil.badArgument();
        }
        return giftCardService.recharge(userId, cardNumber, amount,shopId);
    }

    @ApiOperation("clvoer支付-「礼物卡充值｜支付」")
    @GetMapping("/balanceRechargeByClover")
    @LogAnno
    public ResponseUtil.Response balanceRechargeByClover(@ApiIgnore@LoginUser Integer userId,
                                                         @RequestParam("shopId")Integer shopId,
                                                         @RequestParam("cardNumber")String cardNumber,
                                                         @RequestParam("amount")BigDecimal amount,
                                                         @RequestParam("token") String token){
        return giftCardService.balanceRechargeByClover(userId,shopId,cardNumber,amount,token);
    }




    /**
     * 余额充值礼物卡
     *
     * @param userId     用户id
     * @param cardNumber 卡号
     * @param amount     量
     * @param shopId     商店id
     * @return {@link ResponseUtil.Response}
     */
    @ApiOperation(value = "余额充值礼物卡")
    @ApiImplicitParams({
            @ApiImplicitParam(name = "cardNumber",value = "礼物卡号",required = true),
            @ApiImplicitParam(name = "amount",value = "金额",required = true),
            @ApiImplicitParam(name = "shopId",value = "商店ID",required = true)
    })
    @GetMapping(value = {"balanceRecharge"})
    @LogAnno
    public ResponseUtil.Response balanceRecharge(@ApiIgnore@LoginUser Integer userId, @RequestParam String cardNumber,
                                                 @RequestParam BigDecimal amount,Integer shopId){
        return giftCardService.balanceRecharge(userId, cardNumber, amount,shopId);
    }

    /**
     * 礼物卡购买礼物卡  （自己给自己购买）
     *
     * @param userId         用户id
     * @param cardBuyCardDto 卡买卡dto
     * @return {@link ResponseUtil.Response}
     */
    @ApiOperation(value = "礼物卡购买礼物卡")
    @PostMapping(value = {"cardBuyCard"})
    @LogAnno
    public ResponseUtil.Response cardBuyCard(@ApiIgnore@LoginUser Integer userId,
                                             @Valid @RequestBody CardBuyCardDTO cardBuyCardDto){
        return giftCardService.cardBuyCard(userId,cardBuyCardDto);
    }

    @ApiOperation("clover-「礼物卡购买|给自己买」")
    @ApiImplicitParams({
            @ApiImplicitParam(name = "shopId",value = "商店ID"),
            @ApiImplicitParam(name = "userId",value = "用户ID"),
            @ApiImplicitParam(name = "buyCardId",value = "被购买卡ID"),
            @ApiImplicitParam(name = "token",value = "卡令牌"),
            @ApiImplicitParam(name = "amount",value = "金额")
    })
    @GetMapping(value = "cardBuyClover")
    @LogAnno
    public ResponseUtil.Response cardBuyClover(@RequestParam("shopId") Integer shopId,
                                               @ApiIgnore @LoginUser Integer userId,
                                               @RequestParam("buyCardId") Integer buyCardId,
                                               @RequestParam("token") String  token,
                                               @RequestParam("amount") BigDecimal amount){
        return giftCardService.cardBuyClover(shopId,userId,buyCardId,token,amount);
    }

    @ApiOperation("clover-「礼物卡购买|赠送」")
    @PostMapping(value = "/cardBuyCloverGivee")
    @LogAnno
    public ResponseUtil.Response cardBuyCloverGivee(@ApiIgnore@LoginUser Integer userId,
                                                    @Valid@RequestBody CardBuyCloverGiveeDTO cardBuyCloverGiveeDTO){
        return giftCardService.cardBuyCloverGivee(userId,cardBuyCloverGiveeDTO);
    }

    /**
     * 礼物卡买礼物卡赠送
     *
     * @param userId              用户id
     * @param cardBuyGiveeCardDto 礼物卡买礼物卡赠送dto
     * @return {@link ResponseUtil.Response}
     */
    @ApiOperation(value = "礼物卡买礼物卡赠送")
    @PostMapping(value = {"cardBuyGiveeCard"})
    @LogAnno
    public ResponseUtil.Response cardBuyGiveeCard(@ApiIgnore@LoginUser Integer userId,
                                                  @Valid @RequestBody CardBuyGiveeCardDTO cardBuyGiveeCardDto){
        return giftCardService.cardBuyGiveeCard(userId,cardBuyGiveeCardDto);
    }


    /**
     * 余额购买礼物卡  （自己给自己购买）
     *
     * @param userId          用户id
     * @param moneyBuyCardDto 钱买卡dto
     * @return {@link ResponseUtil.Response}
     */
    @ApiOperation(value = "余额购买礼物卡")
    @PostMapping(value = {"moneyBuyCard"})
    @LogAnno
    public ResponseUtil.Response moneyBuyCard(@ApiIgnore@LoginUser Integer userId,
                                              @Valid @RequestBody MoneyBuyCardDTO moneyBuyCardDto){
        return giftCardService.moneyBuyCard(userId,moneyBuyCardDto);
    }

    /**
     * 余额购买礼物卡赠送
     *
     * @param userId               用户id
     * @param moneyBuyGiveeCardDto 余额购买礼物卡赠送dto
     * @return {@link ResponseUtil.Response}
     */
    @ApiOperation(value = "余额购买礼物卡赠送")
    @PostMapping(value = {"moneyBuyGiveeCard"})
    @LogAnno
    public ResponseUtil.Response moneyBuyGiveeCard(@ApiIgnore@LoginUser Integer userId,
                                                   @Valid @RequestBody MoneyBuyGiveeCardDTO moneyBuyGiveeCardDto){
        return giftCardService.moneyBuyGiveeCard(userId,moneyBuyGiveeCardDto);
    }




    /**
     * 历史
     * 充值和购买，转入转出
     *
     * @param userId     用户id
     * @param cardNumber 卡号
     * @param page       页面
     * @param limit      限制
     * @param sort       排序
     * @param order      订单
     * @return {@link Object}
     */
    @GetMapping("bill/list")
    @LogAnno
    public Object history(@LoginUser Integer userId,
                          @NotNull String cardNumber,
                          @RequestParam(defaultValue = "1") Integer page,
                          @RequestParam(defaultValue = "1000") Integer limit,
                          @Sort @RequestParam(defaultValue = "add_time") String sort,
                          @Order @RequestParam(defaultValue = "desc") String order) {
        if(userId == null){
            return ResponseUtil.unlogin();
        }
        return giftCardService.bill(userId, cardNumber, page, limit, sort, order);
    }

    /**
     * 绑定
     * 绑定实体卡
     *
     * @param userId     用户id
     * @param cardNumber 卡号
     * @param password   密码
     * @return {@link Object}
     */
    @PutMapping("bind")
    @LogAnno
    public Object bind(@LoginUser Integer userId,@NotNull String cardNumber,@NotNull String password){
        if(userId == null){
            return ResponseUtil.unlogin();
        }
        return giftCardService.bind(userId,cardNumber,password);
    }

    /**
     * 转移了
     * 礼物卡转出
     *
     * @param userId          用户id
     * @param cardUserId      卡用户id
     * @param givenCardUserId 鉴于卡用户id
     * @param amount          量
     * @return {@link Object}
     */
    @PutMapping("transferOut")
    @LogAnno
    @Transactional
    public Object transferOut(@LoginUser Integer userId,@NotNull Integer cardUserId,@NotNull Integer givenCardUserId, BigDecimal amount){
        if(userId == null){
            return ResponseUtil.unlogin();
        }
        return giftCardService.transferOut(userId,cardUserId,givenCardUserId,amount);
    }

    /**
     * 除了目前卡片
     * 获取除了当前礼物卡的该用户其他礼物卡
     *
     * @param userId     用户id
     * @param cardUserId 卡用户id
     * @return {@link Object}
     */
    @GetMapping("exceptCurrentCard")
    @LogAnno
    public Object exceptCurrentCard(@LoginUser Integer userId,@NotNull Integer cardUserId){
        if(userId == null){
            return ResponseUtil.unlogin();
        }
        return giftCardService.exceptCurrentCard(userId,cardUserId);
    }

    /**
     * 删除
     * 删除余额为零的礼物卡
     *
     * @param userId     用户id
     * @param cardUserId 卡用户id
     * @return {@link Object}
     */
    @DeleteMapping("delete")
    @LogAnno
    public Object delete(@LoginUser Integer userId,@NotNull Integer cardUserId){
        if(userId == null){
            return ResponseUtil.unlogin();
        }
        return giftCardService.delete(cardUserId);
    }

}
